// The Application State System
// 
// This whole thing is to manage game states. For example pause, run, and 
// menu states. For each application state, we create an own class 
// inheriting AppState.hpp. So each application state has the same basic 
// functions like enter, exit, pause, resume, and update as well as its
// own Camera and SceneManager.
// 
// The second important part of this system is the AppStateManager.hpp.
// Its task is to maange all the game states and connect them. To do so, 
// the manager has a stack of active states and always executes the one on 
// top of the stack. At any time, you can put another state on the stack 
// that is then used until it is popped from the stack. In this case, the 
// manager resumes executing the state that was below the one just removed. 
// When there arent any active states left, the manager closes the whole 
// application. Somewhat similar to the activation record concept. 

#ifndef APP_STATE_HPP
#define APP_STATE_HPP

#include "OgreFramework.hpp"

class AppState;

// AppStateListener will be inherited by the AppStateManager but has to
// be defined here. 
class AppStateListener
{
	public: 

		// Constructor/Destructor
		AppStateListener() {};
		virtual ~AppStateListener() {};

		virtual void manageAppState(Ogre::String stateName, AppState* state) = 0;

		virtual AppState*		findByName(Ogre::String stateName) = 0;
		virtual void			changeAppState(AppState *state) = 0;
		virtual bool			pushAppState(AppState* state) = 0;
		virtual void			popAppState() = 0;
		virtual void			pauseAppState() = 0;
		virtual void			shutdown() = 0;
		virtual void			popAllAndPushAppState(AppState* state) = 0;
};

// AppState is the blueprint from which each actual application state will inherit.
class AppState : public OIS::KeyListener, public OIS::MouseListener
{
	public: 
		
		// Creates the AppState, must be given a parent and name.
		static void create(AppStateListener* parent, const Ogre::String name) {};

		// Destroys the resources.
		void destroy() { delete this; }

		// The various controls for the different states. All of these are meant
		// to be overridden by the different states that will be created.
		virtual void enter() = 0;
		virtual void exit() = 0;
		virtual bool pause() { return true; };
		virtual void resume() {};
		virtual void update(double timeSinceLastFrame) = 0;

	protected:

		// True constructor
		AppState() {};

		// Functions used to perform actions on AppStates.
		AppState* findByName(Ogre::String stateName) { return m_pParent->findByName(stateName); }
		void changeAppState(AppState* state) { m_pParent->changeAppState(state); }
		bool pushAppState(AppState* state) { return m_pParent->pushAppState(state); }
		void popAppState() { m_pParent->popAppState(); }
		void shutdown() { m_pParent->shutdown(); }
		void popAllAndPushAppState(AppState* state) { m_pParent->popAllAndPushAppState(state); }

		// Parent of this AppState.
		AppStateListener*	m_pParent;

		// Each AppState has its own Camera, SceneManager, and FrameEvent.
		Ogre::Camera*		m_pCamera;
		Ogre::SceneManager*	m_pSceneMgr;
		Ogre::FrameEvent	m_FrameEvent;
		

};

// The last part of this file is a big #define statement. It defines the macro 
// DECLARE_APPSTATE_CLASS via which you can later create the game states.
#define DECLARE_APPSTATE_CLASS(T)										\
static void create(AppStateListener* parent, const Ogre::String name)	\
{																		\
	T* myAppState = new T();											\
	myAppState->m_pParent = parent;										\
	parent->manageAppState(name, myAppState);							\
}

#endif